/**
 * Copyright (c) 2010-2011 Pierre Labatut
 *
 * This file is part of Space-Chronicles project.
 *
 * Space-Chronicles is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or <http://code.google.com/p/space-chronicles/>.
 */
package space.input;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import space.input.Record.Frame;

/**
 *
 * @author Pierre Labatut
 */
public class Record implements Iterable<Frame>, Serializable{

    private final List<Frame> list = new ArrayList<Frame>();

    public static Record load(File file) {
        if (file == null) {
            throw new NullPointerException();
        }

        try {
            final InputStream is = new FileInputStream(file);
            final ObjectInputStream ois = new ObjectInputStream(is);
            final Record result = (Record) ois.readObject();
            ois.close();
            return result;
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(ex);
        }
    }

    public void save(File file) {
        if (file == null) {
            throw new NullPointerException();
        }
        try {
            final OutputStream os = new FileOutputStream(file);
            final ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(this);
            oos.close();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    public Frame addFrame() {
        final Frame frame = new Frame();
        list.add(frame);
        return frame;
    }

    Frame getCurrentFrame() {
        return list.get(list.size() - 1);
    }

    public Iterator<Frame> iterator() {
        return Collections.unmodifiableList(list).iterator();
    }

    public static class Frame implements Serializable {

        private final Map<String, Object> map = new HashMap<String, Object>();

        double getDouble(final String key) {
            final Object obj = map.get(key);
            if (obj == null) {
                throw new IllegalArgumentException();
            }
            return (Double) obj;
        }

        float getFloat(final String key) {
            final Object obj = map.get(key);
            if (obj == null) {
                throw new IllegalArgumentException();
            }
            return (Float) obj;
        }

        Frame getFrame(final String key) {
            final Object obj = map.get(key);
            return (Frame) obj;
        }

        void putDouble(final String key, final double value) {
            final Object obj = map.put(key, value);
            if (obj != null) {
                throw new IllegalArgumentException();
            }
        }

        void putFrame(final String key, final Frame value) {
            final Object obj = map.put(key, value);
            if (obj != null) {
                throw new IllegalArgumentException();
            }
        }

        void putFloat(final String key, final float value) {
            final Object obj = map.put(key, value);
            if (obj != null && (Float) obj != value) {
                throw new IllegalArgumentException();
            }
        }

        void putString(String key, String value) {
            final Object obj = map.put(key, value);
            if (obj != null && value.equals(obj) == false) {
                throw new IllegalArgumentException();
            }
        }
    }
}
